package agents;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import agents.exceptions.ActionFailedException;
import agents.resource.ResourceAgent;
import agents.task.TaskAgent;
import domain.Segment;

/**
 * virtuele voorstelling van de fysische omgeving waarin de agents leven; 
 * wordt gebruikt om een agent te zoeken op een bepaalde plaats
 */
public final class Environment {
	
	/* *****  singleton access **** */
	
	public static Environment getInstance() {
		return instance;
	}
	
	private Environment() {}
	private static Environment instance = new Environment();
	
	/* ****** execute actions ***** */
	public void react(List<Action> actions) {
		int nbPrevActions = actions.size();
		boolean done = (nbPrevActions == 0);
		
		while(!done) {
			List<Action> actionsToPerform = new ArrayList<Action>(actions);
			for(Action action : actionsToPerform) {
				try {
					action.performAction();
					actions.remove(action);
				} catch(ActionFailedException e) {
					//doe niks
				}
			}
			if(nbPrevActions == actions.size() || actions.size() == 0) done = true;
			nbPrevActions = actions.size();
		}
	}
	
	/* *** alle agents *** */
	
	private Collection<Agent> agents = new ArrayList<Agent>();
	
	public void addAgent(Agent agent) {
		agents.add(agent);
	}
	public void addAllAgents(Collection<Agent> newAgents){
		agents.addAll(newAgents);
	}
	
	//smijt IllegalStateException wanneer agent niet verwijderd mag worden op dit ogenblik
	public void removeAgent(Agent agent) {
		if(agent instanceof ResourceAgent) ((ResourceAgent) agent).removeResource();
		agents.remove(agent);
	}
	
	public void removeAgents(Collection<Agent> agents) {
		for(Agent a : agents) {
			removeAgent(a);
		}
	}
	
	/* ***** resource agents **** */
	
	public ResourceAgent getResourceAgentAt(Segment s) {
		if(s == null) return null;
		for(ResourceAgent resAgent : getResourceAgents()) {
			if(resAgent.hasSegment(s)) return resAgent;
		}
		return null;
	}
	
	private Collection<ResourceAgent> getResourceAgents() {
		Collection<ResourceAgent> resAgents = new ArrayList<ResourceAgent>();
		for(Agent a : agents) {
			if(a instanceof ResourceAgent) resAgents.add((ResourceAgent) a);
		}
		return resAgents;
	}
	
	private Collection<TaskAgent> getTaskAgents() {
		Collection<TaskAgent> taskAgents = new ArrayList<TaskAgent>();
		for(Agent a : agents) {
			if(a instanceof TaskAgent) taskAgents.add((TaskAgent) a);
		}
		return taskAgents;
	}
	
	/* ***** task agents ***** */
	public TaskAgent getTaskAgentAt(Segment s) {
		for(TaskAgent taskAgent : getTaskAgents()) {
			if(taskAgent.getCar().getPosition() == s) return taskAgent;
		}
		return null;
	}
	
}
